data = {}

if CLIENT then
	data._buffer = ""
	data._messages = 0

	function data.Receive( umsg )
		data._messages = (data._messages or 0) + 1

		data._buffer = data._buffer .. umsg:ReadString() --append to the buffer

		if (umsg:ReadBool()) then
			local buffer = glon.decode(data._buffer)
			local func = nil

			data._buffer = ""	--clear the data buffer
			data._messages = 0

			for _, _name in pairs( string.Explode( ".", buffer.n) ) do
				if (func) then
					func = func[_name]
				else
					func = _G[_name]
				end
			end

			func(unpack(buffer.a))
		end
	end
	usermessage.Hook("data.Receive", data.Receive)
end

if SERVER then
	if (!data._history) then data._history = {} end

	function data.Send( name, ... )
		local packetSize = 250
		local i = 0
		local args = {...}
		local historyid = name

		if (type(name) == "table") then
			historyid = name[2]
			name = name[1]

			historyid = name .. historyid
		end


		local nocache = args[table.Count(args)]	--use last arg as Player

		if (type(nocache) == "String" && nocache == "nocache") then
			nocache = true
			table.remove( args, table.Count(args) )
		else
			nocache = false
		end


		local ply = args[table.Count(args)]	--use last arg as Player

		if (type(ply) == "Player") then
			table.remove( args, table.Count(args) )

			historyid = historyid .. ply:SteamID() --append player id for caches
		else
			ply = nil
		end

		--encode the data to convert to a string
		local dataE = glon.encode({n = name, a = args})

		--cache checks if enabled
		if (!nocache) then
			--if same as last call then dont send (save bandwidth)
			if (data._history[historyid] && data._history[historyid] == dataE) then return end

			--save in history
			data._history[historyid] = dataE

			--keep cache down under 1000 for performance
			if (table.Count(data._history) > 1000) then data._history[table.GetFirstKey(data._history)] = nil end
		end

		repeat
			local dataNS = string.sub( dataE, i, i+packetSize-1 )

			i = i + packetSize

			umsg.Start( "data.Receive", ply )
			umsg.String( dataNS )

			--tell the system this is the last part of the message
			if (i >= string.len(dataE)) then
				umsg.Bool( true )
			end

			umsg.End()
		until (string.len(dataE) <= i || string.len(dataNS) == 0)
	end
end